#include "ucdinputfile.h"
//#include "camera.h"
//#include "GL/glut.h"
#include "visStreamline.h"
#include "visFlowClustering.h"

using std::cout;
using std::endl;

using namespace visualization;

Model t;
Camera c;
int mouse_x;
int mouse_y;
double xmin, xmax, ymin, ymax, zmin, zmax;
complex_ *results;
intgResults *streamline;

void idle()
{
	glutPostRedisplay();
}

void processmouse(int button, int state, int x, int y)
{
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
		{
			mouse_x = x;
			mouse_y = y;
			glutIdleFunc(idle);
		}
		else
		{
			glutIdleFunc(0);
		}
		break;
	}
}

void procecckey(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'x':
		//renderer.Render(rb);
		break;
	default:
		break;
	}
}

void renderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	c.SetupCamera();
	//t.DrawSurfaceWithLight();

	if(abs(zmin == zmax) < 1e-6)
	{
		zmin = 0;
		zmax = xmax;		
	}

	glColor3f(0., 0., 1.0);
	
	glBegin(GL_LINES);
//1
		glColor3f(1., 0., 0.0);
    	glVertex3f(xmin, ymin, zmin);
		glVertex3f(xmax, ymin, zmin);

		glColor3f(0., 1., 0.0);
		glVertex3f(xmin, ymin, zmin);
		glVertex3f(xmin, ymax, zmin);

		glColor3f(0., 0., 1.0);
		glVertex3f(xmin, ymin, zmin);
		glVertex3f(xmin, ymin, zmax);

		glColor3f(0.3, 0.2, 0.5);
//2
		glVertex3f(xmin, ymin, zmax);
		glVertex3f(xmax, ymin, zmax);

		glVertex3f(xmin, ymin, zmax);
		glVertex3f(xmin, ymax, zmax);
//3
		glVertex3f(xmin, ymax, zmax);
		glVertex3f(xmax, ymax, zmax);
//4
		glVertex3f(xmin, ymax, zmin);
		glVertex3f(xmin, ymax, zmax);

		glVertex3f(xmin, ymax, zmin);
		glVertex3f(xmax, ymax, zmin);
//5
		glVertex3f(xmax, ymax, zmin);
		glVertex3f(xmax, ymin, zmin);

		glVertex3f(xmax, ymax, zmin);
		glVertex3f(xmax, ymax, zmax);
//6
		glVertex3f(xmax, ymin, zmax);
		glVertex3f(xmax, ymax, zmax);

		glVertex3f(xmax, ymin, zmax);
		glVertex3f(xmax, ymin, zmin);
	glEnd();

	std::vector<double> co;
	glPointSize(3);
	glBegin(GL_POINTS);		
		for(size_t i = 0; i < t.getPntNumberOfModel(); i++)
		{
			if(results[i].r < 0) { glColor3f(1.0, 0.0, 0.0); }
			else{ glColor3f(0.0, 0.0, 1.0); }
			t.getPointCoordinates(i+1, co);
			glVertex3f(co[0], co[1], co[2]);				
		}
	glEnd();
	glColor3f(0.1, 0.3, 0.4);

	for(size_t i = 0; i < streamline -> size(); i++)
	{
		glBegin(GL_LINE_STRIP);		
			for(size_t j = 0; j < (*streamline)[i].size(); j++)
				glVertex3f((*streamline)[i][j].getX(), (*streamline)[i][j].getY(), (*streamline)[i][j].getZ());
		glEnd();
	}

	glutSwapBuffers();
}

void reshape(int width, int height)
{
	c.ViewPort(width, height);
	c.AutoAdjust(t);
}

void drag(int x, int y)
{
	c.TrackBall(mouse_x, mouse_y, x, y);
	mouse_x = x;
	mouse_y = y;
}

int main(int argc, char *argv[])
{
	string filename;
	cin >> filename;
	cout << filename << endl;
	UCDInputFile file(filename);

	if(file.FGetModel(t) != 0)
	{
		exit(-1);
	}
	t.buildKDTree();
	t.getBound(xmin, xmax, ymin, ymax, zmin, zmax);

	visStreamline s(&t);

	cout << "Input the number of streamlines you want..." << endl;
	int num;
	while(cin >> num)
	{
		if(num > 3)
			break;
		else
		{
			cout << "Reinput please..." << endl;
		}
	}
	num = sqrt(num);

	double xStp = (xmax - xmin)/(num-1);
	double yStp = (ymax - ymin)/(num-1);

	visualization::Point *sources = new visualization::Point[num * num];

	int indx = 0;
	for(double i = xmin; i <= xmax; i+=xStp)
	{
		for(double j = ymin; j <= ymax; j+=yStp)
		{
			sources[indx].setCoordinates(i, j, 0);
			indx++;
		}
	}
	s.setIntegrationDouble();
	s.setSources(sources, num * num);
	s.setParameters(0.1, 200);

	delete []sources;

	streamline = s.integrate();

//////////////////////////////////////////////////////////////////////////

	int part = 1;
    visFlowClustering fc(&t);

	fc.setAlpha(0.5);
    fc.initMatrix();
	fc.segmentField(part);
	results = fc.getEigVec(0);

	c.ViewPort(200, 200);
	c.AutoAdjust(t);
	c.Zoom(0.03);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(200,200);
	glutCreateWindow("GLUT Test");
	glDisable(GL_LINE_SMOOTH);
	glDisable(GL_POINT_SMOOTH);
	glDisable(GL_POLYGON_SMOOTH);
	glDisable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	glutDisplayFunc(renderScene);
	glutReshapeFunc(reshape);
	glutMouseFunc(processmouse);
	glutKeyboardFunc(procecckey);
	glutMotionFunc(drag);
	glutMainLoop();
	return 0;
}

